/**
 * 地图瓦片缓存管理器
 * 用于缓存地图瓦片数据，提高地图加载速度
 */

class MapTileCache {
  constructor() {
    this.dbName = "MapTileCache";
    this.dbVersion = 1;
    this.storeName = "tiles";
    this.db = null;
    this.maxCacheSize = 100 * 1024 * 1024; // 100MB 最大缓存大小
    this.maxAge = 7 * 24 * 60 * 60 * 1000; // 7天过期时间
  }

  /**
   * 初始化IndexedDB数据库
   */
  async init() {
    if (this.db) return this.db;

    return new Promise((resolve, reject) => {
      const request = indexedDB.open(this.dbName, this.dbVersion);

      request.onerror = () => {
        console.error("Failed to open IndexedDB:", request.error);
        reject(request.error);
      };

      request.onsuccess = () => {
        this.db = request.result;
        resolve(this.db);
      };

      request.onupgradeneeded = (event) => {
        const db = event.target.result;

        // 创建瓦片存储对象存储
        if (!db.objectStoreNames.contains(this.storeName)) {
          const store = db.createObjectStore(this.storeName, {
            keyPath: "key",
          });
          store.createIndex("timestamp", "timestamp", { unique: false });
          store.createIndex("size", "size", { unique: false });
        }
      };
    });
  }

  /**
   * 生成瓦片缓存键
   */
  generateTileKey(url) {
    // 从URL中提取x, y, z参数
    const urlObj = new URL(url);
    const pathParts = urlObj.pathname.split("/");
    const searchParams = new URLSearchParams(urlObj.search);

    // 尝试从URL路径或查询参数中提取瓦片坐标
    let x, y, z;

    // 检查查询参数
    if (
      searchParams.has("x") &&
      searchParams.has("y") &&
      searchParams.has("z")
    ) {
      x = searchParams.get("x");
      y = searchParams.get("y");
      z = searchParams.get("z");
    } else {
      // 从URL模板中提取（假设URL包含{x}, {y}, {z}占位符的实际值）
      const match = url.match(
        /x=(\d+).*y=(\d+).*z=(\d+)|\/(\d+)\/(\d+)\/(\d+)/
      );
      if (match) {
        x = match[1] || match[4];
        y = match[2] || match[5];
        z = match[3] || match[6];
      }
    }

    return `${urlObj.hostname}_${z}_${x}_${y}`;
  }

  /**
   * 获取缓存的瓦片
   */
  async getTile(url) {
    try {
      await this.init();
      const key = this.generateTileKey(url);

      const transaction = this.db.transaction([this.storeName], "readonly");
      const store = transaction.objectStore(this.storeName);
      const request = store.get(key);

      return new Promise((resolve, reject) => {
        request.onsuccess = () => {
          const result = request.result;
          if (result) {
            // 检查是否过期
            const now = Date.now();
            if (now - result.timestamp > this.maxAge) {
              // 过期了，删除并返回null
              this.deleteTile(key);
              resolve(null);
            } else {
              // 返回缓存的数据
              resolve(result.data);
            }
          } else {
            resolve(null);
          }
        };

        request.onerror = () => {
          console.error("Failed to get tile from cache:", request.error);
          resolve(null); // 缓存失败时返回null，让系统从网络加载
        };
      });
    } catch (error) {
      console.error("Error getting tile from cache:", error);
      return null;
    }
  }

  /**
   * 缓存瓦片数据
   */
  async cacheTile(url, data) {
    try {
      await this.init();
      const key = this.generateTileKey(url);

      // 检查缓存大小
      const currentSize = await this.getCacheSize();
      const dataSize = this.getDataSize(data);

      if (currentSize + dataSize > this.maxCacheSize) {
        // 清理旧的缓存
        await this.cleanOldCache();
      }

      const transaction = this.db.transaction([this.storeName], "readwrite");
      const store = transaction.objectStore(this.storeName);

      const cacheItem = {
        key: key,
        url: url,
        data: data,
        timestamp: Date.now(),
        size: dataSize,
      };

      const request = store.put(cacheItem);

      return new Promise((resolve, reject) => {
        request.onsuccess = () => {
          resolve(true);
        };

        request.onerror = () => {
          console.error("Failed to cache tile:", request.error);
          resolve(false);
        };
      });
    } catch (error) {
      console.error("Error caching tile:", error);
      return false;
    }
  }

  /**
   * 删除指定瓦片缓存
   */
  async deleteTile(key) {
    try {
      await this.init();
      const transaction = this.db.transaction([this.storeName], "readwrite");
      const store = transaction.objectStore(this.storeName);
      const request = store.delete(key);

      return new Promise((resolve) => {
        request.onsuccess = () => resolve(true);
        request.onerror = () => resolve(false);
      });
    } catch (error) {
      console.error("Error deleting tile:", error);
      return false;
    }
  }

  /**
   * 清理旧的缓存数据
   */
  async cleanOldCache() {
    try {
      await this.init();
      const transaction = this.db.transaction([this.storeName], "readwrite");
      const store = transaction.objectStore(this.storeName);
      const index = store.index("timestamp");

      // 获取所有缓存项，按时间戳排序
      const request = index.openCursor();
      const itemsToDelete = [];
      let totalSize = 0;

      return new Promise((resolve) => {
        request.onsuccess = (event) => {
          const cursor = event.target.result;
          if (cursor) {
            const item = cursor.value;
            totalSize += item.size;

            // 如果总大小超过限制的80%，或者数据过期，标记删除
            if (
              totalSize > this.maxCacheSize * 0.8 ||
              Date.now() - item.timestamp > this.maxAge
            ) {
              itemsToDelete.push(item.key);
            }

            cursor.continue();
          } else {
            // 删除标记的项目
            const deletePromises = itemsToDelete.map((key) =>
              this.deleteTile(key)
            );
            Promise.all(deletePromises).then(() => {
              console.log(`Cleaned ${itemsToDelete.length} old cache items`);
              resolve();
            });
          }
        };

        request.onerror = () => {
          console.error("Error cleaning old cache:", request.error);
          resolve();
        };
      });
    } catch (error) {
      console.error("Error in cleanOldCache:", error);
    }
  }

  /**
   * 获取当前缓存大小
   */
  async getCacheSize() {
    try {
      await this.init();
      const transaction = this.db.transaction([this.storeName], "readonly");
      const store = transaction.objectStore(this.storeName);
      const request = store.getAll();

      return new Promise((resolve) => {
        request.onsuccess = () => {
          const items = request.result;
          const totalSize = items.reduce(
            (sum, item) => sum + (item.size || 0),
            0
          );
          resolve(totalSize);
        };

        request.onerror = () => {
          console.error("Error getting cache size:", request.error);
          resolve(0);
        };
      });
    } catch (error) {
      console.error("Error in getCacheSize:", error);
      return 0;
    }
  }

  /**
   * 获取缓存统计信息
   */
  async getCacheStats() {
    try {
      await this.init();
      const transaction = this.db.transaction([this.storeName], "readonly");
      const store = transaction.objectStore(this.storeName);
      const request = store.getAll();

      return new Promise((resolve) => {
        request.onsuccess = () => {
          const items = request.result;
          const totalSize = items.reduce(
            (sum, item) => sum + (item.size || 0),
            0
          );
          const tileCount = items.length;

          let oldestTimestamp = null;
          let newestTimestamp = null;

          if (items.length > 0) {
            const timestamps = items
              .map((item) => item.timestamp)
              .sort((a, b) => a - b);
            oldestTimestamp = timestamps[0];
            newestTimestamp = timestamps[timestamps.length - 1];
          }

          resolve({
            tileCount,
            totalSize,
            oldestTimestamp,
            newestTimestamp,
          });
        };

        request.onerror = () => {
          console.error("Error getting cache stats:", request.error);
          resolve({
            tileCount: 0,
            totalSize: 0,
            oldestTimestamp: null,
            newestTimestamp: null,
          });
        };
      });
    } catch (error) {
      console.error("Error in getCacheStats:", error);
      return {
        tileCount: 0,
        totalSize: 0,
        oldestTimestamp: null,
        newestTimestamp: null,
      };
    }
  }

  /**
   * 清空所有缓存
   */
  async clearAllCache() {
    try {
      await this.init();
      const transaction = this.db.transaction([this.storeName], "readwrite");
      const store = transaction.objectStore(this.storeName);
      const request = store.clear();

      return new Promise((resolve) => {
        request.onsuccess = () => {
          console.log("All tile cache cleared");
          resolve(true);
        };

        request.onerror = () => {
          console.error("Error clearing cache:", request.error);
          resolve(false);
        };
      });
    } catch (error) {
      console.error("Error in clearAllCache:", error);
      return false;
    }
  }

  /**
   * 计算数据大小（字节）
   */
  getDataSize(data) {
    if (data instanceof ArrayBuffer) {
      return data.byteLength;
    } else if (data instanceof Blob) {
      return data.size;
    } else if (typeof data === "string") {
      return new Blob([data]).size;
    } else {
      // 对于其他类型，尝试序列化后计算大小
      try {
        return new Blob([JSON.stringify(data)]).size;
      } catch {
        return 1024; // 默认1KB
      }
    }
  }
}

// 创建单例实例
const mapTileCache = new MapTileCache();

export default mapTileCache;
